var crypto = require('crypto');
var cryptojs = require('cryptojs').Crypto;
var parseString = require('xml2js').parseString;
var DateHelper = require('./dateHelper');
var JsonToXmlHelper = require('./JsonToXmlHelper');
var fs = require('fs');
var FormatString = require('./FormatString');
//var GlobalConfig = require('GlobalConfig');

var WeiXinPayHelper = {

    random:function(num) {
        var items = '0123456789'.split('');
        var vcode = '';
        for (var i = 0; i < (num||6); i++) {
            var rnd = Math.random();
            var item = Math.round(rnd * (items.length - 1));
            vcode += items[item];
        }
        return vcode;
    },

    getNonceStr:function(){
      
       var date = DateHelper.pattern(new Date(), "yyyyMMddHHmmss");
       return date + this.random(8);
    },

    getSortStr:function(sort_result){
        var sign_str = "";
        for(var item in sort_result){
            if(sort_result[item] == '') {
                continue;
            }
            if(sign_str != ""){
                sign_str += "&"
            }
            sign_str += item;
            sign_str += "=";
            sign_str += sort_result[item];
        }

        return sign_str;
    },

    getXmlString:function(params){
        var keys = Object.keys(params);
        var result_str = "";
        result_str += "<xml>";
        result_str += JsonToXmlHelper.jsonToXml(params);
        result_str += "</xml>";

        console.log(result_str);
        return result_str;
    },

    getSortObject:function(params){
        var params_sort = Object.keys(params).sort();

        var sort_result = {};
        for(var i=0;i<params_sort.length;i++){
            sort_result[params_sort[i]] = params[params_sort[i]]
        }

        return sort_result;
    },

    getSign:function(sortobj, seller_key){
        var sign_str = this.getSortStr(sortobj);
        var stringSignTemp= sign_str + "&key=" + seller_key;
        return cryptojs.MD5(stringSignTemp).toUpperCase();
    },

    getQrcodeSign:function(sortobj, seller_key){
        var sign_str = this.getSortStr(sortobj);
        var stringSignTemp= sign_str + "&key=" + seller_key;
        return cryptojs.MD5(stringSignTemp).toUpperCase();
    },

    getQrcodeSuccessXmlString: function(result){
        return this.getXmlString(result);
    },

    getSuccessXmlString: function(){
        return this.getXmlString({return_code: 'SUCCESS', return_msg: 'OK'})
    },

    getErrorXmlString: function(error){
        return this.getXmlString({return_code: 'FAIL', return_msg: ''+error})
    },

    xmlToJson: function(xml, fnCb){
         parseString(xml, { explicitArray : false, ignoreAttrs : true }, function(err, result){
            var json_result = JSON.parse(JSON.stringify(result.xml));
            fnCb(json_result);
        });
    },    

    qrcodeLink: function(appid, mch_id, seller_key, product_id){
        var link = "weixin://wxpay/bizpayurl?sign=#{sign}&appid=#{appid}&mch_id=#{mch_id}&product_id=#{product_id}&time_stamp=#{time_stamp}&nonce_str=#{nonce_str}";
        
        var time_stamp = DateHelper.getTimeBySecond();
        var nonce_str = this.getNonceStr();

        var params = {
            appid: appid,
            mch_id: mch_id,
            product_id: product_id,
            time_stamp: time_stamp,
            nonce_str: nonce_str
        }

        var sort_result = this.getSortObject(params);
        params.sign = this.getSign(sort_result, seller_key);
        return FormatString.formatString(link, params)
    },

    order_sign:function(appid, mch_id, seller_key, body, detail, out_trade_no, total_fee, spbill_create_ip, notify_url, trade_type, openid, product_id, fnCb){
        //统一下单接口

        var request = require('request');
        var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        var params = {
            appid:appid,
            mch_id:mch_id,
            nonce_str:this.getNonceStr(),
            body:body,
            detail:detail,
            out_trade_no:out_trade_no,
            total_fee:total_fee,
            spbill_create_ip:spbill_create_ip,
            notify_url:notify_url,
            trade_type:trade_type
        };

        if(trade_type == "JSAPI"){
            params.openid = openid;
        }

        if(trade_type == "NATIVE"){
            params.product_id = product_id;
        }

        console.log("params", params);

        var sort_result = this.getSortObject(params);
        params.sign = this.getSign(sort_result, seller_key);
        var xmlString = WeiXinPayHelper.getXmlString(params);

        var options = {
            uri:url,
            method:'POST',
            body:xmlString
        }

        request(options, function (error, response, body) {
            console.log(error, body);
            if (!error && response.statusCode == 200) {
        
                parseString(body, { explicitArray : false, ignoreAttrs : true }, function(err, result){
                     console.log("result:", result);
                    var json_result = JSON.parse(JSON.stringify(result.xml));
                    var weixin_sign = json_result.sign;
                    delete json_result.sign;
                    var sort_result = WeiXinPayHelper.getSortObject(json_result);
                    var self_sign = WeiXinPayHelper.getSign(sort_result, seller_key);
                    console.log("weixin_sign:", weixin_sign, "self_sign:", self_sign);
                    if(weixin_sign == self_sign){
                        if(json_result.return_code == "SUCCESS" && json_result.result_code == "SUCCESS"){
                            console.log(json_result);
                            if(fnCb){
                                fnCb(0, json_result);
                            }
                        }else{
                            if(fnCb){
                                fnCb(1, {
                                    result_code:json_result.result_code,
                                    err_code:json_result.err_code,
                                    err_code_des:json_result.err_code_des
                                });
                            }
                        }
                    }else{
                       if(fnCb){
                            fnCb(1, {
                                    result_code:json_result.result_code,
                                    err_code:json_result.err_code,
                                    err_code_des:"签名错误"
                            });
                        }
                    }
                    
                });
                   
            }else{
                fnCb(1, {});
            }
        });

    },

    result_verify:function(xml, seller_key, fnCb){
        //
        parseString(xml, { explicitArray : false, ignoreAttrs : true }, function(err, result){
                var json_result = JSON.parse(JSON.stringify(result.xml));
                
                var weixin_sign = json_result.sign;
                delete json_result.sign;
                var sort_result = WeiXinPayHelper.getSortObject(json_result);
                var self_sign = WeiXinPayHelper.getSign(sort_result, seller_key);
                if(weixin_sign == self_sign){
                    if(json_result.return_code == "SUCCESS" && json_result.result_code == "SUCCESS"){
                        console.log(json_result);
                        fnCb(0, json_result);   
                    }else{
                        fnCb(1, json_result);
                    }
                }else{
                    fnCb(1, json_result);     
                } 
        });
    },

    qrcode_result_verify: function(xml, seller_key, fnCb){
        parseString(xml, { explicitArray : false, ignoreAttrs : true }, function(err, result){
                var json_result = JSON.parse(JSON.stringify(result.xml));
                
                var weixin_sign = json_result.sign;
                delete json_result.sign;
                var sort_result = WeiXinPayHelper.getSortObject(json_result);
                var self_sign = WeiXinPayHelper.getSign(sort_result, seller_key);
                if(weixin_sign == self_sign){
                    fnCb(0, json_result);   
                }else{
                    fnCb(1, json_result);     
                } 
        });
    },

    sendRedpack: function(mch_key, wxappid, mch_id, mch_billno, send_name, re_openid, total_amount, total_num, wishing, client_ip, act_name, remark, scene_id, fnCb){
        //发送红包
        var request = require('request');
        var url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";

        var params = {
            nonce_str: this.getNonceStr(),
            wxappid: wxappid,
            mch_id:  mch_id,
            mch_billno: mch_billno,
            send_name: send_name,
            re_openid: re_openid,
            total_amount: total_amount,
            total_num: total_num,
            wishing: wishing,
            client_ip: client_ip,
            act_name: act_name,
            remark: remark,
            scene_id: scene_id
        };

        console.log("params", params);

        var sort_result = this.getSortObject(params);
        params.sign = this.getSign(sort_result, mch_key);
        var xmlString = WeiXinPayHelper.getXmlString(params);

        var options = {
            uri:url,
            method:'POST',
            key: GlobalConfig.is_test?fs.readFileSync('./framework/rsa_pem/test_apiclient_key.pem'):fs.readFileSync('./framework/rsa_pem/apiclient_key.pem'),
            cert: GlobalConfig.is_test?fs.readFileSync('./framework/rsa_pem/test_apiclient_cert.pem'):fs.readFileSync('./framework/rsa_pem/apiclient_cert.pem'),
            body:xmlString
        }

        request(options, function (error, response, body) {
            console.log(error);
            if (!error && response.statusCode == 200) {
        
                parseString(body, { explicitArray : false, ignoreAttrs : true }, function(err, result){
                    var json_result = JSON.parse(JSON.stringify(result.xml));
                    if(json_result.return_code == "SUCCESS" && json_result.result_code == "SUCCESS"){
                        console.log(json_result);
                        if(fnCb){
                            fnCb(0, json_result);
                        }
                    }else{
                        if(fnCb){
                            fnCb(1, {
                                result_code:json_result.result_code,
                                err_code:json_result.err_code,
                                err_code_des:json_result.err_code_des
                            });
                        }
                    }
                    
                });
                   
            }else{
                fnCb(1, {});
            }
        });
    },

    refund: function(mch_key, mch_appid, mch_id, out_trade_no, out_refund_no, total_fee, refund_fee, fnCb){
        //退款
        var request = require('request');
        url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        var params = {
            appid: mch_appid,
            mch_id: mch_id,
            nonce_str: this.getNonceStr(),
            out_trade_no: out_trade_no,
            out_refund_no: out_refund_no,   //退款单号
            total_fee: total_fee,           //订单总金额
            refund_fee: refund_fee,         //退款总金额
            op_user_id: mch_id,             //操作员id
        }

        var sort_result = this.getSortObject(params);
        params.sign = this.getSign(sort_result, mch_key);
        var xmlString = WeiXinPayHelper.getXmlString(params);

        var options = {
            uri:url,
            method:'POST',
            key: GlobalConfig.is_test?fs.readFileSync('./framework/rsa_pem/test_apiclient_key.pem'):fs.readFileSync('./framework/rsa_pem/apiclient_key.pem'),
            cert: GlobalConfig.is_test?fs.readFileSync('./framework/rsa_pem/test_apiclient_cert.pem'):fs.readFileSync('./framework/rsa_pem/apiclient_cert.pem'),
            body:xmlString
        }

        request(options, function (error, response, body) {
            console.log("error:", error, body);
            if (!error && response.statusCode == 200) {
                parseString(body, { explicitArray : false, ignoreAttrs : true }, function(err, result){
                    var json_result = JSON.parse(JSON.stringify(result.xml));
                    var weixin_sign = json_result.sign;
                    delete json_result.sign;
                    var sort_result = WeiXinPayHelper.getSortObject(json_result);
                    var self_sign = WeiXinPayHelper.getSign(sort_result, mch_key);
                    if(weixin_sign == self_sign){
                        if(json_result.return_code == "SUCCESS" && json_result.result_code == "SUCCESS"){
                            console.log(json_result);
                            if(fnCb){
                                fnCb(0, json_result);
                            }
                        }else{
                            if(fnCb){
                                fnCb(1, {
                                    result_code:json_result.result_code,
                                    err_code:json_result.err_code,
                                    err_code_des:json_result.err_code_des
                                });
                            }
                        }
                    }else{
                       if(fnCb){
                            fnCb(1, {
                                    result_code:json_result.result_code,
                                    err_code:json_result.err_code,
                                    err_code_des:"签名错误"
                            });
                        }
                    }
                    
                });
                   
            }else{
                fnCb(1, {});
            }
        });

    },

    queryrefund: function(mch_key, mch_appid, mch_id, out_refund_no, fnCb){
        var request = require('request');
        url = "https://api.mch.weixin.qq.com/pay/refundquery";

        var params = {
            appid: mch_appid,
            mch_id: mch_id,
            nonce_str: this.getNonceStr(),
            out_refund_no: out_refund_no,
        }        
        var sort_result = this.getSortObject(params);
        params.sign = this.getSign(sort_result, mch_key);
        var xmlString = WeiXinPayHelper.getXmlString(params);

        var options = {
            uri:url,
            method:'POST',
            body:xmlString
        }

        request(options, function (error, response, body) {
            console.log(error);
            if (!error && response.statusCode == 200) {
                parseString(body, { explicitArray : false, ignoreAttrs : true }, function(err, result){
                    var json_result = JSON.parse(JSON.stringify(result.xml));
                    var weixin_sign = json_result.sign;
                    delete json_result.sign;
                    var sort_result = WeiXinPayHelper.getSortObject(json_result);
                    var self_sign = WeiXinPayHelper.getSign(sort_result, mch_key);
                    
                    if(weixin_sign == self_sign){
                        if(json_result.return_code == "SUCCESS" && json_result.result_code == "SUCCESS"){
                            console.log(json_result);
                            if(fnCb){
                                fnCb(0, json_result);
                            }
                        }else{
                            if(fnCb){
                                fnCb(1, {
                                    result_code:json_result.result_code,
                                    err_code:json_result.err_code,
                                    err_code_des:json_result.err_code_des
                                });
                            }
                        }
                    }else{
                       if(fnCb){
                            fnCb(1, {
                                    result_code:json_result.result_code,
                                    err_code:json_result.err_code,
                                    err_code_des:"签名错误"
                            });
                        }
                    }
                    
                });
                   
            }else{
                fnCb(1, {});
            }
        });      

    },

    transfer: function(mch_key, mch_appid, mchid, partner_trade_no, openid, check_name, re_user_name, amount, desc, spbill_create_ip, fnCb){
        //转账

        var request = require('request');
        var url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
        var params = {
            mch_appid: mch_appid,
            mchid: mchid,
            nonce_str:this.getNonceStr(),
            partner_trade_no: partner_trade_no,
            openid: openid,
            check_name: check_name,
            re_user_name: re_user_name,
            amount: amount,
            desc: desc,
            spbill_create_ip: spbill_create_ip
        };

        var sort_result = this.getSortObject(params);
        params.sign = this.getSign(sort_result, mch_key);
        var xmlString = WeiXinPayHelper.getXmlString(params);

        var options = {
            uri:url,
            method:'POST',
            key: GlobalConfig.is_test?fs.readFileSync('./framework/rsa_pem/test_apiclient_key.pem'):fs.readFileSync('./framework/rsa_pem/apiclient_key.pem'),
            cert: GlobalConfig.is_test?fs.readFileSync('./framework/rsa_pem/test_apiclient_cert.pem'):fs.readFileSync('./framework/rsa_pem/apiclient_cert.pem'),
            body:xmlString
        }

        request(options, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                parseString(body, { explicitArray : false, ignoreAttrs : true }, function(err, result){
                    var json_result = JSON.parse(JSON.stringify(result.xml));
                    if(json_result.return_code == "SUCCESS" && json_result.result_code == "SUCCESS"){
                        console.log(json_result);
                        if(fnCb){
                            fnCb(0, json_result);
                        }
                    }else{
                        if(fnCb){
                            fnCb(1, {
                                result_code:json_result.result_code,
                                err_code:json_result.err_code,
                                err_code_des:json_result.err_code_des
                            });
                        }
                    }
              
                });
                   
            }else{
                fnCb(1, {});
            }
        });
    }

}

module.exports = WeiXinPayHelper;
